package me.dengfengdecao.android.photogallery;

import android.app.SearchManager;
import android.app.SearchableInfo;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.SearchView;

import java.util.ArrayList;


public class PhotoGalleryFragment extends VisibleFragment {

    private static final String TAG = "PhotoGalleryFragment";

    private GalleryItemAdapter mGalleryItemAdapter;
    private ArrayList<GalleryItem> mItems;
    private ThumbnailDownloader mThumbnailDownloader;

    GridView mGridView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setRetainInstance(true);
        setHasOptionsMenu(true);

        // 启动AsyncTask，继而触发后台线程并调用doInBackground(...)方法。
        updateItems();

        // 将Handler传递给ThumbnailDownloader
        // 注意，此Handler是在onCreate方法内创建的，默认与主线程的Looper关联
        mThumbnailDownloader = new ThumbnailDownloader(new Handler());
        // 设置Listener，使用返回的Bitmap执行UI更新操作
        mThumbnailDownloader.setListener(new ThumbnailDownloader.Listener<ImageView>() {
            @Override
            public void onThumbnailDownloaded(ImageView imageView, Bitmap thumbnail, String picUrl) {
	            // 防止图面缓存引起的错位问题，给每个imageView添加一个tag,用URL做标识，加载图片时
	            // 只有当前的URL和要加载图片的imageView的tag中的URL相同时，才加载.
	            imageView.setTag(picUrl);
                imageView.setImageBitmap(thumbnail);
            }
        });

	    // 启动后台线程
        mThumbnailDownloader.start();

    }

    public void updateItems() {
        new FetchItemsTask().execute();
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment_photo_gallery, container, false);

        mGridView = (GridView) v.findViewById(R.id.gridView);

        // 当设备旋转重新生成GridView时,可重新为其配置对应的adapter
        setupAdapter();

        mGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                GalleryItem item = mItems.get(position);
                // 图片所在的网址
                Uri picUri = Uri.parse(item.getPicUrl());

                // 通过隐式intent实现点击图片跳转到网页浏览
                //Intent i = new Intent(Intent.ACTION_VIEW, picUri);

                // 通过显式intent实现点击图片后在应用WebView中浏览
                Intent i = new Intent(getActivity(), PhotoPageActivity.class);
                // 附加图片网址数据
                i.setData(picUri);

                startActivity(i);
            }
        });

        return v;
    }

    // 内部类，调用并测试新添加的网络连接代码,使用异步加载，防止阻塞主线程
    // 使用后台线程最简便的方式是使用AsyncTask工具类，但不适用于重复且长时间运行的任务
    // 第一个类型参数可指定输入参数的类型（可以是一个或多个）
    // 第二个类型参数可指定发送进度更新需要的类型
    // 第三个类型参数是AsyncTask返回结果的数据类型
    private class FetchItemsTask extends AsyncTask<Void, Void, Void> {

        // 运行在后台线程
        @Override
        protected Void doInBackground(Void... params) {
            // 从默认的SharedPreferences中取回搜索查询信息。
            String query = PreferenceManager.getDefaultSharedPreferences(getActivity())
                    .getString(NetFetcher.PREF_SEARCH_QUERY, null);
            // 将查询的结果返回
            if (query != null) {
                mItems = new NetFetcher().search(query);
            } else {
                // 从目标网站获取数据并记录下日志
                mItems = new NetFetcher().fetchItems();
            }

            return null;
        }

        // 该方法在doInBackground方法执行之后执行，接收从doInBackground(...)方法获取的列表数据，
        // 并将返回数据放入mItems变量，然后调用setupAdapter()方法更新GridView视图的adapter。
        // 运行在主线程上
        @Override
        protected void onPostExecute(Void aVoid) {
            mGalleryItemAdapter = new GalleryItemAdapter(mItems);
            setupAdapter();
        }
    }

    // GridView无GridFragment便利类，只能自己实现adapter的管理
    // 该方法根据当前模型数据的不同状态，可对应设置GridView的adapter
    void setupAdapter() {
        if (getActivity() == null || mGridView == null) return;

        // 设置绑定到GridView上的数据集
        mGridView.setAdapter(mGalleryItemAdapter);

    }

    // 这个适配器内部类提供要显示在GridView上的数据
    private class GalleryItemAdapter extends ArrayAdapter<GalleryItem> {


        public GalleryItemAdapter(ArrayList<GalleryItem> items) {
            super(getActivity(), 0, items);
        }

        // 返回一个显示初始占位图片的ImagerView
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            // 复用convertView，减少item view 的加载次数
	        ViewHolder viewHolder;
            if (convertView == null) {
                convertView = getActivity().getLayoutInflater().inflate(R.layout.gallery_item, parent, false);
	            viewHolder = new ViewHolder();
	            viewHolder.mImageView = (ImageView) convertView.findViewById(R.id.gallery_item_imageView);
	            viewHolder.mImageView.setImageResource(R.drawable.imageview_loading);  // 设置预览图
	            convertView.setTag(viewHolder);
            } else {
	            viewHolder = (ViewHolder) convertView.getTag();
            }

            // 关联使用ThumbnailDownloader,通过position获取正确的GalleryItem并传入ImageView和其Url
			String picUrl = getItem(position).getPicUrl();

            mThumbnailDownloader.queueThumbnail(viewHolder.mImageView, picUrl);


            return convertView;
        }

        // 使用holder，减少获取item中子控件的次数
        class ViewHolder {
            private ImageView mImageView;
        }
    }

    // 添加搜索、清除菜单
    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        super.onCreateOptionsMenu(menu, inflater);
        inflater.inflate(R.menu.menu_photo_gallery, menu);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            // 获得SearchView
            MenuItem searchItem = menu.findItem(R.id.menu_item_search);
            SearchView searchView = (SearchView) searchItem.getActionView();
            // 获得系统级别的搜索服务
            SearchManager searchManager = (SearchManager) getActivity().getSystemService(Context.SEARCH_SERVICE);
            // 获得当前activity完整的组件名称
            ComponentName componentName = getActivity().getComponentName();
            // 获得关联searchable.xml的activity的相关信息
            SearchableInfo searchableInfo = searchManager.getSearchableInfo(componentName);
            // 将相关信息通知给SearchView
            searchView.setSearchableInfo(searchableInfo);
        }

    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.menu_item_search :
                // 当用户点击搜索时调用
                //getActivity().onSearchRequested();
                getActivity().startSearch("性感", true, null, false);
                return true;
            case R.id.menu_item_clear :
                // 从shared preferences中清除搜索信息并更新列表项
                PreferenceManager.getDefaultSharedPreferences(getActivity())
                        .edit()
                        .putString(NetFetcher.PREF_SEARCH_QUERY, null)
                        .commit();
                updateItems();
                return true;
            case R.id.menu_item_toggle_polling :
                // 启动定时器
                boolean shouldStartAlarm = !PollService.isServiceAlarmOn(getActivity());
                PollService.setServiceAlarm(getActivity(), shouldStartAlarm);

                // 3.0版本后的系统需invalidateOptionsMenu()方法回调onPrepareOptionsMenu(Menu)方法并刷新菜单项。
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
                    getActivity().invalidateOptionsMenu();
                }

                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    // 检查定时器的开关状态，然后更新menu_item_toggle_polling的标题文字，提供反馈信息供用户查看
    // 还需在onOptionsItemSelected调用invalidateOptionsMenu()方法以可以在3.0以上版本生效
    @Override
    public void onPrepareOptionsMenu(Menu menu) {
        super.onPrepareOptionsMenu(menu);

        MenuItem toggleItem = menu.findItem(R.id.menu_item_toggle_polling);
        if (PollService.isServiceAlarmOn(getActivity())) {
            toggleItem.setTitle(R.string.stop_polling);
        } else {
            toggleItem.setTitle(R.string.start_polling);
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        // 如不终止HandlerThread，它会一直运行下去
        mThumbnailDownloader.quit();
        Log.d(TAG, "onDestroy 退出后台线程！");
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        // 调用清除等待队列的所有请求方法
        mThumbnailDownloader.clearQueue();
    }
}
